home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Info 1994 March
/
Internet Info CD-ROM (Walnut Creek) (March 1994).iso
/
networking
/
ip
/
ka9q
/
net_des.arc
/
MAIN.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-12-05
|
4KB
|
203 lines
/* Encrypt/decrypt command compatible with Sun's "des" command */
#include <stdio.h>
char iv[8]; /* Initial vector for CBC mode */
int block;
main(argc,argv)
int argc;
char *argv[];
{
int c,cnt,encrypt,decrypt,hexflag;
register int i;
char key[8],tkey1[20],tkey2[20],*akey,*getpass();
extern char *optarg;
hexflag = block = encrypt = decrypt = 0;
akey = NULL;
while((c = getopt(argc,argv,"hedk:b")) != EOF){
switch(c){
case 'h':
hexflag++;
break;
case 'e':
encrypt++;
break;
case 'd':
decrypt++;
break;
case 'k':
akey = optarg;
break;
case 'b':
block++;
break;
}
}
if(encrypt == 0 && decrypt == 0){
fprintf(stderr,"Usage: des -e|-d [-h] [-k key]\n");
exit(2);
}
if(akey == NULL){
/* No key on command line, prompt for it */
memset(tkey1,0,sizeof(tkey1));
memset(tkey2,0,sizeof(tkey2));
for(;;){
akey = getpass("Enter key: ");
strncpy(tkey1,akey,sizeof(tkey1));
akey = getpass("Enter key again: ");
strncpy(tkey2,akey,sizeof(tkey2));
if(strncmp(tkey1,tkey2,sizeof(tkey1)) != 0){
fprintf(stderr,"Key mistyped, try again\n");
} else
break;
}
akey = tkey1;
}
if(hexflag){
for(i=0;i<16;i++){
if(htoa(akey[i]) == -1){
fprintf(stderr,"Non-hex character in key\n");
exit(1);
}
}
gethex(key,akey,8);
} else {
strncpy(key,akey,8);
/* Set up key, determine parity bit */
for(cnt = 0; cnt < 8; cnt++){
c = 0;
for(i=0;i<7;i++)
if(key[cnt] & (1 << i))
c++;
if((c & 1) == 0)
key[cnt] |= 0x80;
else
key[cnt] &= ~0x80;
}
}
/* Blot out original key */
i = strlen(akey);
i = (i < 8) ? i : 8;
memset(akey,0,i);
desinit(0);
setkey(key);
/* Initialize IV to all zeros */
memset(iv,0,8);
if(encrypt){
doencrypt();
} else {
dodecrypt();
}
}
/* Encrypt standard input to standard output */
doencrypt()
{
char work[8],*cp,*cp1;
int cnt,i;
for(;;){
if((cnt = fread(work,1,8,stdin)) != 8){
/* Put residual byte count in the last block.
* Note that garbage is left in the other bytes,
* if any; this is a feature, not a bug, since it'll
* be stripped out at decrypt time.
*/
work[7] = cnt;
}
if(!block){
/* CBC mode; chain in last cipher word */
cp = work;
cp1 = iv;
for(i=8; i!=0; i--)
*cp++ ^= *cp1++;
}
endes(work); /* Encrypt block */
if(!block){ /* Save outgoing ciphertext for chain */
memcpy(iv,work,8);
}
fwrite(work,1,8,stdout);
if(cnt != 8)
break;
}
}
dodecrypt()
{
char work[8],nwork[8],ivtmp[8],*cp,*cp1;
int cnt,i;
cnt = fread(work,1,8,stdin); /* Prime the pump */
for(;;){
if(!block){ /* Save incoming ciphertext for chain */
memcpy(ivtmp,work,8);
}
dedes(work);
if(!block){ /* Unchain block, save ciphertext for next */
cp = work;
cp1 = iv;
for(i=8; i!=0; i--){
*cp++ ^= *cp1++;
}
memcpy(iv,ivtmp,8);
}
/* Save buffer pending next read */
memcpy(nwork,work,8);
/* Try to read next block */
cnt = fread(work,1,8,stdin);
if(cnt != 8){ /* Can "only" be 0 if not 8 */
/* Prev block was last one, write appropriate number
* of bytes
*/
cnt = nwork[7];
if(cnt < 0 || cnt > 7){
fprintf(stderr,"Corrupted file or wrong key\n");
} else if(cnt != 0)
fwrite(nwork,1,cnt,stdout);
exit(0);
} else {
/* Now okay to write previous buffer */
fwrite(nwork,1,8,stdout);
}
}
}
/* Convert hex/ascii nybble to binary */
int
htoa(c)
char c;
{
if(c >= '0' && c <= '9')
return c - '0';
if(c >= 'a' && c <= 'f')
return 10 + c - 'a';
if(c >= 'A' && c <= 'F')
return 10 + c - 'A';
return -1;
}
/* Convert bytes from hex/ascii to binary */
gethex(result,cp,cnt)
register char *result;
register char *cp;
register int cnt;
{
while(cnt-- != 0){
*result = htoa(*cp++) << 4;
*result++ |= htoa(*cp++);
}
}
#ifdef DEBUG
put8(cp)
register char *cp;
{
int i;
for(i=0;i<8;i++){
fprintf(stderr,"%02x ",*cp++ & 0xff);
}
}
#endif